Skip to content

feat(brainstormer): axis label namespace + axis-aware status/dispatch filter (#126)#138

Merged
hadamrd merged 1 commit into
trunkfrom
loop/126-iter
May 28, 2026
Merged

feat(brainstormer): axis label namespace + axis-aware status/dispatch filter (#126)#138
hadamrd merged 1 commit into
trunkfrom
loop/126-iter

Conversation

@hadamrd
Copy link
Copy Markdown
Owner

@hadamrd hadamrd commented May 28, 2026

Summary

Closes #126. Introduces the axis:<slug> GitHub label namespace + the operator-facing surface to group / filter the loop's work by topical concern (dispatch, cli, observability, …) without changing how issues are queued.

  • forge-loop status (+--json) groups open loop:ready issues by axis with an unaligned bucket + yellow warning when any open issue carries no axis:* label.
  • forge-loop run --axis <name> (repeatable, union) filters dispatch. Omitting the flag is byte-identical to today.
  • forge-loop status --axis <name> narrows the grouped view.
  • Active axis filter is logged + emitted to events.jsonl (axis_filter_active, axis_filter_empty) so focused-sprint launches are auditable.
  • New forge_loop.axis pure-helper module + docs/axis-labels.md.

Test plan

  • tests/test_cli_axis_filter.py — axis helpers, status --json shape, multi-axis dedup, Rich warning, CLI flag wiring.
  • tests/test_dispatch_axis_filter.py — single + union filter, regression guard for no-filter path, ready-gate priority, malformed-label safety, mixed-case normalisation, zero-match clean exit.
  • pytest tests/test_cli.py tests/test_dispatch_slot_accounting.py tests/test_stuck_sweep.py — green (52 passed).

🤖 Generated with Claude Code

… filter

Closes #126.

Introduces the `axis:<slug>` GitHub label namespace as pure plumbing so
operators can focus a sprint on a single topical concern (dispatch, cli,
observability, …) without changing how issues are queued.

Surface:
- `forge-loop status` now groups open `loop:ready` issues by `axis:*`
  label. JSON gains `axes` + `unaligned_count` + `axis_filter` keys.
  Issues with no axis land in an `unaligned` bucket and a yellow warning
  row is rendered in the human surface.
- `forge-loop run --axis <name>` (repeatable, union semantics) narrows
  dispatch to matching issues. Omitting the flag preserves pre-#126
  behaviour byte-for-byte.
- `forge-loop status --axis <name>` narrows the grouped view.
- The runner logs the active axis filter at startup and emits
  `axis_filter_active` / `axis_filter_empty` events per tick so a
  focused-sprint launch is auditable from `forge-loop events`.

Implementation:
- New `forge_loop.axis` module: pure helpers (extract_axes,
  group_by_axis, filter_issues_by_axes, parse_filter_env).
  Lowercase-normalises mixed-case labels; treats empty-slug labels
  (`axis:`) as unaligned.
- CLI threads `--axis` through env var `LOOP_AXIS_FILTER` so the tick
  loop can read it without a new kwarg on `run_loop`.
- Dispatch widens its `top_issues` fetch only when a filter is active,
  then trims back to `cfg.parallel` from the matched subset.

Docs: `docs/axis-labels.md` walks the namespace + edge-case matrix.

Tests:
- tests/test_cli_axis_filter.py — pure axis helpers, `status --json`
  payload shape, multi-axis dedup, Rich warning row, CLI flag wiring.
- tests/test_dispatch_axis_filter.py — single + union filters, regression
  guard for the no-filter path (identity-preserving), ready-gate priority,
  malformed-label safety, mixed-case normalisation, zero-match clean exit.
@hadamrd hadamrd merged commit 4cc4d8a into trunk May 28, 2026
2 checks passed
@hadamrd hadamrd deleted the loop/126-iter branch May 28, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(brainstormer): axis label namespace + axis-aware status/dispatch filter

1 participant